import httpEnum from "../enum/http.enum"
import funcUtil from "../utils/func.util"

class Auth {
  _options: any
  constructor() {
    this._options = { responseType: "json" }
  }
  get options() {
    const e = this._options
    return e
  }
}
class ReadOnlyStore extends Auth {
  config: any
  url: any
  constructor(e) {
    super(), (this.config = e), (this.url = e.path)
  }
  async read() {
    const { deserialize } = this.config
    let t = null
    return (
      this.config.cachedData && this.config.cachedData.data
        ? (t = this.config.cachedData.data)
        : ((t = await this.config.queue.get(this.config.path, this.options)), this.config.cachedData && (this.config.cachedData.data = t)),
      deserialize(t)
    )
  }
  clearCache() {
    this.config.cachedData && (this.config.cachedData.data = null)
  }
}
class Store extends ReadOnlyStore {
  constructor(e) {
    super(e), (this.config = e)
  }
  async create(e) {
    this.clearCache()
    const { serialize: t } = this.config,
      i = t(e),
      n = Object.assign(Object.assign({}, this.options), { body: i })
    return this.config.queue.put(this.config.path, n)
  }
  async update(e, t) {
    this.clearCache()
    const { serialize: i } = this.config,
      s = i(e, t),
      r = Object.assign(Object.assign({}, this.options), { body: s })
    return this.config.queue.request(this.config.httpMethod || httpEnum.POST, this.config.path, r)
  }
  async delete(e) {
    if ((this.clearCache(), !(e instanceof Array))) return this.config.queue.delete(this.config.path, this.options)
    for (const t of e) await this.config.queue.delete(`${this.config.path}/${t.sid}`, this.options)
  }
  get acceptsPartial() {
    return this.config.httpMethod === httpEnum.PATCH
  }
}
class JsonStore extends ReadOnlyStore {
  acceptsPartial: boolean
  constructor(e) {
    super(e)
    this.config = e
    this.acceptsPartial = !1
    this.config.batchUpdate = "batchUpdate" in this.config && this.config.batchUpdate
  }
  async create(e) {
    throw Error("Not implemented")
  }
  updateBatch(e, t) {
    const { serialize: i } = this.config,
      s = [],
      r = [...new Set([...Object.keys(e), ...Object.keys(t)])]
    for (const i of r) {
      e[i] || t[i] || s.push(this.config.queue.delete(`${this.config.path}/${i}`, this.options))
    }
    const o = i(e, t),
      a = Object.assign(Object.assign({}, this.options), { body: o })
    return s.push(this.config.queue.request(this.config.httpMethod || httpEnum.POST, this.config.path, a)), Promise.all(s)
  }
  updateInternal(e, t) {
    const { serialize: i } = this.config,
      r = [],
      o = Object.assign({}, this.options),
      a = Object.keys(e),
      l = Object.keys(t),
      c = funcUtil.arrayToObj(a.concat(l))
    for (const s in c) {
      const a = c[s],
        l = e[a] || t[a]
      if (l) {
        const e = {}
        e[a] = l
        const s = {},
          c = t[a]
        c && (s[a] = c)
        const h = i(e, s)
        ;(o.body = h), r.push(this.config.queue.request(this.config.httpMethod || httpEnum.POST, this.config.path, o))
      } else r.push(this.config.queue.delete(`${this.config.path}/${a}`, this.options))
    }
    return Promise.all(r)
  }
  async update(e, t?) {
    this.clearCache(), await (this.config.batchUpdate ? this.updateBatch(e, t || {}) : this.updateInternal(e, t || {}))
  }
  async delete(e) {
    throw Error("Not implemented")
  }
}
export default {
  gh: ReadOnlyStore,
  yh: Store,
  MU: JsonStore,
  ReadOnlyStore,
  Store,
  JsonStore
}
